﻿using UnityEngine;
using System.Collections;


namespace Suimono.Core
{

	public class fx_buoyancy : MonoBehaviour {


		//PUBLIC VARIABLES
		public bool applyToParent = false;
		public bool engageBuoyancy = false;		// 有浮力作用
		public float activationRange = 500.0f;	// 激活范围
		//public bool inheritForce = false;		// 继承力
		public bool keepAtSurface = false;		// 保持平面
		public float buoyancyOffset = 0.0f;		// 浮力偏移
		public float buoyancyStrength = 1.0f;	// 浮力强度
		// public float forceAmount = 1.0f;		// 强制量
		// public float forceHeightFactor = 0.0f;	// 强制高度系数

		// PRIVATE VARIABLES
		private float maxVerticalSpeed = 5.0f;
		private float surfaceRange = 0.2f;
		private float buoyancy = 0.0f;
		private float waveHeight = 0.0f;
		private float underwaterLevel = 0.0f;
		private bool isUnderwater = false;
		// 吃水线：高度+偏移量-0.5f
		private	float waterline = 0.0f;
		private Transform physTarget;
		private Transform realParent;
		private float modTime = 0.0f;
		private float splitFac = 1.0f;	// 拆分比
		private Rigidbody rigidbodyComponent;
		private bool hasWater = false;
		//private Vector2 forceAngles = new Vector2(0.0f,0.0f);
		//private float forceSpeed = 0.0f;
		private float displace;

		private int randSeed;
		private MyRandom buyRand;

		//collect for GC
		private Vector3 gizPos;
		private float buoyancyFactor;
		private float forceMod;
		private bool heightInit = false;
		private bool isEnabled = true;
		private bool performHeight = false;
		private float currRange = -1.0f;
		private float camRange = -1.0f;
		private Vector3 currCamPos = new Vector3(-1f,-1f,-1f);
		private Vector3 physPosition;
		private float lerpSurfacePosTime = 0f;
		private float targetYPosition;
		private float startYPosition;
		
		private Camera setCameraComponent;

		private OceanToolkit.Ocean ocean;

		void OnDrawGizmos (){
			gizPos = transform.position;
			gizPos.y += 0.03f;
			Gizmos.DrawIcon(gizPos, "gui_icon_buoy.psd", true);
			gizPos.y -= 0.03f;
		}



		void Start () {

			if (GameObject.Find("Ocean") != null){
				ocean = (OceanToolkit.Ocean) FindObjectOfType(typeof(OceanToolkit.Ocean));
			}

			// 获取随机种子
			randSeed = System.Environment.TickCount;
			buyRand = new MyRandom(randSeed);

			// 获取父对象fx_buoyancy的数量
			if (applyToParent){
				var buoyancyObjects = transform.parent.gameObject.GetComponentsInChildren<fx_buoyancy>();
				if (buoyancyObjects != null){
					// // 拆分比
					splitFac = 1f/buoyancyObjects.Length;
				}
			}

			// 获取物理对象
			if (applyToParent){
				realParent = physTarget = this.transform.parent.transform;
				while(physTarget != null && rigidbodyComponent == null){
					rigidbodyComponent = physTarget.GetComponent<Rigidbody>();
					if(rigidbodyComponent == null)
					{
						physTarget = physTarget.parent.transform;
					}
				}
			} else {
				realParent = physTarget = this.transform;
				if (physTarget != null){
					if (rigidbodyComponent == null){
						rigidbodyComponent = GetComponent<Rigidbody>();
					}
				}
			}
			setCameraComponent = Camera.main;
		}
		



		void FixedUpdate(){

			SetUpdate();
			// 需要上浮的距离
			displace = Mathf.Clamp(waveHeight - (transform.position.y+buoyancyOffset-0.5f),0.0f,5.0f);
			maxVerticalSpeed = displace;
			buoyancy = 1 + (displace * buoyancyStrength);
		}





		void SetUpdate () {


		//set Random
		if (buyRand == null) buyRand = new MyRandom(randSeed);
		//检查是否进行高度处理(下沉、上浮)
		performHeight = true;
		//检查是否有效
		if (!isEnabled){
			performHeight = false;
		}
		else{
			if (realParent != null && Camera.main != null){
				// 检查与相机的距离是否在有效范围内
				if (activationRange > 0f){
					currRange = Vector3.Distance(Camera.main.transform.position, realParent.transform.position);
					if (currRange >= activationRange){
						performHeight = false;
					}
				}
				
				if(performHeight){
					// 检查是否在视锥内
					camRange = 0.2f;
					if (setCameraComponent != null && performHeight){
						currCamPos = setCameraComponent.WorldToViewportPoint(realParent.transform.position);
						if (currCamPos.x > (1f+camRange) || currCamPos.y > (1f+camRange)){
							performHeight = false;
						}
						else if (currCamPos.x < (0f-camRange) || currCamPos.y < (0f-camRange)){
							performHeight = false;
						}
					}
				}
			}
		}

		// forceHeightFactor = Mathf.Clamp01(forceHeightFactor);
		
		isUnderwater = false;
		underwaterLevel = 0f;
		
		// 吃水线：高度+偏移量-0.5f
		waterline = (transform.position.y+buoyancyOffset-0.5f);			

		// 执行高度检查
		if (performHeight || !heightInit || !hasWater){
			heightInit = true;
			// 获取海水变量
			waveHeight = ocean.GetHeightAt(this.transform.position);
			// 位置点是否有水
			hasWater = true;
		}
		
		// 是否碰到水
		if (waterline < waveHeight){
			isUnderwater = true;
		}
		underwaterLevel =  waveHeight-waterline;

		// 非保持平面
		if (!keepAtSurface) 
		{
			if(rigidbodyComponent) 
				rigidbodyComponent.isKinematic = false;

			if (engageBuoyancy && hasWater){
				// 存在浮力作用 且 有水
				if (rigidbodyComponent && !rigidbodyComponent.isKinematic){
					// 当前没有物理力的影响
					buoyancyFactor = 10.0f;

					if (isUnderwater){
						if (waterline < waveHeight-surfaceRange){								
							// 在水下时给浮力增加垂直力 = 浮力系数 * (垂直浮力 * 质量) * 水下深度 * 作用比
							forceMod = (buoyancyFactor * (buoyancy * rigidbodyComponent.mass) * (underwaterLevel) * splitFac );
							if (forceMod > 0.0001f && rigidbodyComponent.velocity.y < maxVerticalSpeed){
								rigidbodyComponent.AddForceAtPosition(new Vector3(0f,1f,0f) * forceMod, transform.position);
							}
							modTime = 0f;
							
						} else {								
							// 当到达水面或波峰时，减慢垂直速度
							modTime = waterline / (waveHeight+buyRand.Next(0f,0.25f));
							if (rigidbodyComponent.velocity.y > 0f){
								rigidbodyComponent.velocity = new Vector3(
									rigidbodyComponent.velocity.x,
									Mathf.SmoothStep(rigidbodyComponent.velocity.y,0f,modTime),
									rigidbodyComponent.velocity.z);
							}
						}
					
						// // 添加飘动强制量
						// if (inheritForce){
						// 	if (waterline <= waveHeight){
						// 		rigidbodyComponent.AddForceAtPosition(new Vector3(forceAngles.x,0f,forceAngles.y) * (buoyancyFactor*2f) * forceSpeed * splitFac * forceAmount, transform.position);
						// 	}
						// }
					}
					
				}
			}
		}
		else if (hasWater){
			// (刚体高度+偏移)比波浪高度 低，且大于0.25f
			float testPos = (waveHeight - realParent.position.y - buoyancyOffset);
			if (testPos >= -0.25f){
				// 设置刚体存在物理影响
				if (rigidbodyComponent != null){
					rigidbodyComponent.isKinematic = true;
				}

				physPosition = realParent.position;
				physPosition.y = Mathf.Lerp(startYPosition, targetYPosition, lerpSurfacePosTime);
				realParent.position = physPosition;

			} else {
				// 设置刚体不受物理影响
				rigidbodyComponent.isKinematic = false;
			}

			//set timer for smooth blend
			lerpSurfacePosTime += Time.deltaTime * 4f;
			if (lerpSurfacePosTime > 1f){
				lerpSurfacePosTime = 0f;
				startYPosition = realParent.position.y;
				targetYPosition = waveHeight - buoyancyOffset;
			}

		}
	}






	}
}